package org.example.stream;

import org.junit.Test;

import java.text.Collator;
import java.util.*;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * map      功能描述:对集合中所有元素统一处理
 * filter   功能描述:根据条件过滤集合数据
 * distinct 功能描述:去除集合中重复数据
 * limit    功能描述:指定获取集合前x条数据，重新构造一个新的集合
 * skip	 功能描述:排除集合前x条数据，把后面的数据重新构造一个新的集合
 * flatMap  功能描述:对集合中所有元素统一处理
 * sorted   功能描述 : 对集合进行排序
 * anyMatch 功能描述 : 判断集合中是否至少存在一个元素满足条件
 * allMatch 功能描述 : 判断集合中是否所有元素都满足条件
 * noneMatch功能描述 : 判断集合中是否所有元素都不满足条件
 * findAny  功能描述 : 返回当前流中任意元素
 * findFirst功能描述 : 返回当前流中第一个元素
 * forEach  功能描述 : 遍历流
 * collect  功能描述 : 流转换为其他形式
 * reduce   功能描述 : 将流中元素反复结合起来，得到一个值
 * count    功能描述 : 返回流中元素总数
 */
public class StreamTest {

    @Test
    public void myTest(){
        User user1 = new User("1","cg1","0123");
        User user2 = new User("2","cg2","1234");
        User user3 = new User("3","cg3","1235");
        User user4 = new User("4","cg4","1236");
        List<User> userList = new ArrayList<>();
        userList.add(user1);
        userList.add(user2);
        userList.add(user3);
        userList.add(user4);

        //filter 条件过滤
        System.out.println("========================================");
        userList.stream()
                .filter(s -> s.getName().contains("cg2"))//包含 张
                .forEach(System.out::println);
        System.out.println("----------------------------------------");
        //forEach 遍历
        userList.forEach(System.out::println);

        System.out.println("========================================");

        //count 返回数组的数量统计
        System.out.println(userList.stream().count());
        //limit 返回包含cd 取前2条数据
        userList.stream().filter(s -> s.getName().contains("cg")).limit(2).forEach(System.out::println);
        System.out.println("========================================");
        //skip  跳过几个数据然后取
        userList.stream().filter(s -> s.getName().contains("cg")).skip(1).forEach(System.out::println);
        //map 将一种集合转换为另一种集合
        List<User> cg2 = userList.stream().map(user -> {
            if (user.getName().equals("cg2")) {
                user.setPassword("5201314");
            }
            return user;
        }).collect(Collectors.toList());
        cg2.forEach(System.out::println);
        System.out.println("----------------------------------------");
        userList.forEach(System.out::println);
        System.out.println("========================================");
        //sorted 排序 默认升序
//        userList.stream().map(Integer::parseInt).sorted(((o1, o2) -> o2-o1)).forEach(System.out::println);
//        distinct 去重复
        userList.stream().distinct().forEach(System.out::println);
        //reduce 求和  强行转的
//        Integer sumAge=  userList.stream().map(person -> Integer.parseInt(person.getPassword()))
//                .reduce(0,(x,y) -> x+y);
//        System.out.println(sumAge);



    }


    /**
     * map
     * 功能描述:对集合中所有元素统一处理
     * @return : void
     */
    @Test
    public void map(){
        List<String> strings = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
        List<String> mapped = strings.stream().map(str->str+"-itcast").collect(Collectors.toList());
        mapped.stream().forEach(System.out::println);
    }


    /**
     * filter
     * 功能描述:根据条件过滤集合数据
     * @return : void
     */
    @Test
    public void filter(){
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
        filtered.stream().forEach(System.out::println);
    }


    /**distinct
     * 功能描述:去除集合中重复数据
     * @return : void
     */
    @Test
    public void distinct(){
        List<String> strings = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
        List<String> distincted = strings.stream().distinct().collect(Collectors.toList());
        distincted.stream().forEach(System.out::println);
    }


    /**limit
     * 功能描述:指定获取集合前x条数据，重新构造一个新的集合
     * @return : void
     */
    @Test
    public void limit(){
        List<String> strings = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
        List<String> limited = strings.stream().limit(3).collect(Collectors.toList());
        limited.stream().forEach(System.out::println);
    }

    /**skip
     * 功能描述:排除集合前x条数据，把后面的数据重新构造一个新的集合
     * @return : void
     */
    @Test
    public void skip(){
        List<String> strings = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
        List<String> skiped = strings.stream().skip(3).collect(Collectors.toList());
        skiped.stream().forEach(System.out::println);
    }




    /**
     * flatMap
     * 功能描述:对集合中所有元素统一处理
     * @return : void
     */
    @Test
    public void flatMap(){
        List<String> strings = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
        Stream<String> stringStream = strings.stream().map(x -> x);
        Stream<String> stringStream1 = strings.stream().flatMap(x -> Arrays.asList(x.split(" ")).stream());

    }


    /**sorted
     * 功能描述 : 对集合进行排序
     * @return : void
     */
    @Test
    public void sorted(){
        List<String> strings1 = Arrays.asList("abc", "abd", "aba", "efg", "abcd","jkl", "jkl");
        List<String> strings2 = Arrays.asList("张三", "李四", "王五", "赵柳", "张哥","李哥", "王哥");
        List<Integer> strings3 = Arrays.asList(10, 2, 30, 22, 1,0, -9);
        List<String> sorted1 = strings1.stream().sorted().collect(Collectors.toList());
        List<String> sorted2 = strings2.stream().sorted(Collections.reverseOrder(Collator.getInstance(Locale.CHINA))).collect(Collectors.toList());
        List<Integer> sorted3 = strings3.stream().sorted().collect(Collectors.toList());
        sorted1.stream().forEach(System.out::println);
        sorted2.stream().forEach(System.out::println);
        sorted3.stream().forEach(System.out::println);

    }


    /**anyMatch
     * 功能描述 : 判断集合中是否至少存在一个元素满足条件
     * @return : void
     */
    @Test
    public void anyMatch(){
        List<String> strings = Arrays.asList("abc", "abd", "aba", "efg", "abcd","jkl", "jkl");
        boolean b = strings.stream().anyMatch(s -> s == "abc");
        System.out.println(b);
    }


    /**allMatch
     * 功能描述 : 判断集合中是否所有元素都满足条件
     * @return : void
     */
    @Test
    public void allMatch(){
        List<String> strings = Arrays.asList("abc", "abd", "aba", "efg", "abcd","jkl", "jkl");
        boolean b = strings.stream().allMatch(s -> s == "abc");
        System.out.println(b);
    }

    /**noneMatch
     * 功能描述 : 判断集合中是否所有元素都不满足条件
     * @return : void
     */
    @Test
    public void noneMatch(){
        List<String> strings = Arrays.asList("abc", "abd", "aba", "efg", "abcd","jkl", "jkl");
        boolean b = strings.stream().noneMatch(s -> s == "abc");
        System.out.println(b);
    }


    /**findAny
     * 功能描述 : 返回当前流中任意元素
     * @return : void
     */
    @Test
    public void findAny(){
        List<String> strings = Arrays.asList("cv", "abd", "aba", "efg", "abcd","jkl", "jkl");
        Optional<String> any = strings.stream().findAny();
        if(any.isPresent())
            System.out.println(any.get());
    }


    /**findFirst
     * 功能描述 : 返回当前流中第一个元素
     * @return : void
     */
    @Test
    public void findFirst(){
        List<String> strings = Arrays.asList("cv", "abd", "aba", "efg", "abcd","jkl", "jkl");
        Optional<String> first = strings.stream().findFirst();
        if(first.isPresent()) System.out.println(first.get());
    }


    /**forEach
     * 功能描述 : 遍历流
     * @return : void
     */
    @Test
    public void foreach(){
        List<String> strings = Arrays.asList("cv", "abd", "aba", "efg", "abcd","jkl", "jkl");
        strings.stream().forEach(s -> System.out.println(s));
    }


    /**collect
     * 功能描述 : 流转换为其他形式
     * @return : void
     */
    @Test
    public void collect(){
        List<String> strings = Arrays.asList("cv", "abd", "aba", "efg", "abcd","jkl", "jkl");
        Set<String> set = strings.stream().collect(Collectors.toSet());
        List<String> list = strings.stream().collect(Collectors.toList());
        Map<String, String> map = strings.stream().collect(Collectors.toMap(v ->v.concat("_name"), v1 -> v1, (v1, v2) -> v1));
        System.out.println(set);
        System.out.println(list);
        System.out.println(map);
    }


    /**reduce
     * 功能描述 : 将流中元素反复结合起来，得到一个值
     * @return : void
     */
    @Test
    public void reduce(){
        List<String> strings = Arrays.asList("cv", "abd", "aba", "efg", "abcd","jkl", "jkl");
        //reduce方法一
        Optional<String> reduce1 = strings.stream().reduce((acc,item) -> {return acc+item;});
        //reduce方法二
        String reduce2 = strings.stream().reduce("itcast", (acc, item) -> {
            return acc + item;
        });
        //reduce方法三
        ArrayList<String> reduce3 = strings.stream().reduce(
                new ArrayList<String>(),
                new BiFunction<ArrayList<String>, String, ArrayList<String>>() {
                    @Override
                    public ArrayList<String> apply(ArrayList<String> acc, String item) {
                        acc.add(item);
                        return acc;
                    }
                },
                new BinaryOperator<ArrayList<String>>() {
                    @Override
                    public ArrayList<String> apply(ArrayList<String> acc, ArrayList<String> item) {
                        return acc;
                    }
                }
        );
        if(reduce1.isPresent())System.out.println(reduce1.get());
        System.out.println(reduce2);
        System.out.println(reduce3);
    }


    /**count
     * 功能描述 : 返回流中元素总数
     * @return : void
     */
    @Test
    public void count(){
        List<String> strings = Arrays.asList("cv", "abd", "aba", "efg", "abcd","jkl", "jkl");
        long count = strings.stream().count();
        System.out.println(count);
    }




















    @Test
    public void test(){
//        用于通过设置的条件过滤出元素
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
        filtered.stream().forEach(System.out::println);
        System.out.println("==========================================================");

//        返回一个元素各异（根据流所生成元素的hashCode和equals方法实现）的流。
        List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
        numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);
        System.out.println("==========================================================");


//        会返回一个不超过给定长度的流。
        List<String> strings1 = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
        List<String> limited = strings1.stream().limit(3).collect(Collectors.toList());
        limited.stream().forEach(System.out::println);
        System.out.println("==========================================================");


//        返回一个扔掉了前n个元素的流
        List<String> strings2 = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
        List<String> skiped = strings2.stream().skip(3).collect(Collectors.toList());
        skiped.stream().forEach(System.out::println);
        System.out.println("==========================================================");


//        接受一个函数作为参数。这个函数会被应用到每个元素上，并将其映射成一个新的元素（使用映射一词，是因为它和转换类似，但其中的细微差别在于它是“创建一个新版本”而不是去“修改”）。
        List<String> strings3 = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
        List<String> mapped = strings3.stream().map(str->str+"-itcast").collect(Collectors.toList());
        mapped.stream().forEach(System.out::println);
        System.out.println("==========================================================");

//        使用flatMap方法的效果是，各个数组并不是分别映射成一个流，而是映射成流的内容。所有使用map(Arrays::stream)时生成的单个流都被合并起来，即扁平化为一个流。
        List<String> strings4 = Arrays.asList("abc", "abc", "bc", "efg", "abcd","jkl", "jkl");
//        Stream<Character> flatMap = strings4.stream().flatMap(Java8StreamTest::getCharacterByString);


    }
}
